#include <stdio.h>
#include <string.h>
#include <ogcsys.h>
#include <ogc/machine/processor.h>
#include <errno.h>
#include <ogcsys.h>
#include <stdarg.h>
#include <string.h>
#include <network.h>

static struct sockaddr socketassr;
static socklen_t sockx;

static char IP[16];
static bool networkinited = false;
static char incommingIP[50];

void Init_Network(void) {

    if (networkinited) return;

	s32 res;
    res = if_config(IP, NULL, NULL, true);

    if (res < 0) {
        networkinited = false;
        return;
    } else {
        networkinited = true;
        return;
    }
}

bool IsNetworkInit(void) {
    return networkinited;
}

s32 listenforconnect(void)
{
	s32 s = net_socket(AF_INET,SOCK_STREAM,0);
	
	struct sockaddr_in sin;
	memset((void*)&sin,0,sizeof(sin));
	
	sin.sin_family = AF_INET;
	sin.sin_port = 666;
	
	net_bind(s,(struct sockaddr *)&sin,sizeof(sin));
	
	net_listen(s,8);
	s32 ret = net_accept(s,&socketassr,&sockx);
	sprintf(incommingIP, inet_ntoa(sin.sin_addr));
	return ret;
}
s32 send_messagenetwork(s32 server, char *msg,u32 size) {
	return net_write(server, msg, size);
}

u32 rec_messagenetwork(s32 connection, char* buffer, s32 len) {

	int offset = 0;
    while (1) {
        //Fill the buffer with a new batch of bytes from the connection,
        //starting from where we left of in the buffer till the end of the buffer
        s32 bytes_read = net_read(connection, buffer + offset, len);
        //Anything below 0 is an error in the connection
        if (bytes_read < 0) {
            return bytes_read;
        }

		//check if end is reached
		len = len - bytes_read;
		if (len <= 0){
			break;
		}
        offset += bytes_read;
    }
    return 0;
}

char * GetNetworkIP(void) {
    return IP;
}
char * GetIncommingIP(void) {
    return incommingIP;
}
s32 server_connect(u32 ipaddress, u32 socket_port) {
    //Initialize socket
    s32 connection = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (connection < 0) return connection;

    struct sockaddr_in connect_addr;
    memset(&connect_addr, 0, sizeof(connect_addr));
    connect_addr.sin_family = AF_INET;
    connect_addr.sin_port = socket_port;
    connect_addr.sin_addr.s_addr= ipaddress;

    sprintf(incommingIP, "%s", inet_ntoa(connect_addr.sin_addr));

    //Attemt to open the socket
    if (net_connect(connection, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) == -1) {
        net_close(connection);
        return -1;
    }
    return connection;
}
